home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / sound / streams.c < prev    next >
C/C++ Source or Header  |  2000-03-12  |  7KB  |  293 lines

  1. /***************************************************************************
  2.  
  3.   streams.c
  4.  
  5.   Handle general purpose audio streams
  6.  
  7. ***************************************************************************/
  8.  
  9. #include "driver.h"
  10. #include <math.h>
  11.  
  12.  
  13. #define BUFFER_LEN 16384
  14.  
  15. #define SAMPLES_THIS_FRAME(channel) \
  16.     mixer_need_samples_this_frame((channel),stream_sample_rate[(channel)])
  17.  
  18. static int stream_joined_channels[MIXER_MAX_CHANNELS];
  19. static INT16 *stream_buffer[MIXER_MAX_CHANNELS];
  20. static int stream_sample_rate[MIXER_MAX_CHANNELS];
  21. static int stream_buffer_pos[MIXER_MAX_CHANNELS];
  22. static int stream_sample_length[MIXER_MAX_CHANNELS];    /* in usec */
  23. static int stream_param[MIXER_MAX_CHANNELS];
  24. static void (*stream_callback[MIXER_MAX_CHANNELS])(int param,INT16 *buffer,int length);
  25. static void (*stream_callback_multi[MIXER_MAX_CHANNELS])(int param,INT16 **buffer,int length);
  26.  
  27. static int memory[MIXER_MAX_CHANNELS];
  28. static int r1[MIXER_MAX_CHANNELS];
  29. static int r2[MIXER_MAX_CHANNELS];
  30. static int r3[MIXER_MAX_CHANNELS];
  31. static int c[MIXER_MAX_CHANNELS];
  32.  
  33. /*
  34. signal >--R1--+--R2--+
  35.               |      |
  36.               C      R3---> amp
  37.               |      |
  38.              GND    GND
  39. */
  40.  
  41. /* R1, R2, R3 in Ohm; C in pF */
  42. /* set C = 0 to disable the filter */
  43. void set_RC_filter(int channel,int R1,int R2,int R3,int C)
  44. {
  45.     r1[channel] = R1;
  46.     r2[channel] = R2;
  47.     r3[channel] = R3;
  48.     c[channel] = C;
  49. }
  50.  
  51. void apply_RC_filter(int channel,INT16 *buf,int len,int sample_rate)
  52. {
  53.     float R1,R2,R3,C;
  54.     float Req;
  55.     int K;
  56.     int i;
  57.  
  58.  
  59.     if (c[channel] == 0) return;    /* filter disabled */
  60.  
  61.     R1 = r1[channel];
  62.     R2 = r2[channel];
  63.     R3 = r3[channel];
  64.     C = (float)c[channel] * 1E-12;    /* convert pF to F */
  65.  
  66.     /* Cut Frequency = 1/(2*Pi*Req*C) */
  67.  
  68.     Req = (R1*(R2+R3))/(R1+R2+R3);
  69.  
  70.     K = 0x10000 * exp(-1 / (Req * C) / sample_rate);
  71.  
  72.     buf[0] = buf[0] + (memory[channel] - buf[0]) * K / 0x10000;
  73.  
  74.     for (i = 1;i < len;i++)
  75.         buf[i] = buf[i] + (buf[i-1] - buf[i]) * K / 0x10000;
  76.  
  77.     memory[channel] = buf[len-1];
  78. }
  79.  
  80.  
  81.  
  82. int streams_sh_start(void)
  83. {
  84.     int i;
  85.  
  86.  
  87.     for (i = 0;i < MIXER_MAX_CHANNELS;i++)
  88.     {
  89.         stream_joined_channels[i] = 1;
  90.         stream_buffer[i] = 0;
  91.     }
  92.  
  93.     return 0;
  94. }
  95.  
  96.  
  97. void streams_sh_stop(void)
  98. {
  99.     int i;
  100.  
  101.  
  102.     for (i = 0;i < MIXER_MAX_CHANNELS;i++)
  103.     {
  104.         free(stream_buffer[i]);
  105.         stream_buffer[i] = 0;
  106.     }
  107. }
  108.  
  109.  
  110. void streams_sh_update(void)
  111. {
  112.     int channel,i;
  113.  
  114.  
  115.     if (Machine->sample_rate == 0) return;
  116.  
  117.     /* update all the output buffers */
  118.     for (channel = 0;channel < MIXER_MAX_CHANNELS;channel += stream_joined_channels[channel])
  119.     {
  120.         if (stream_buffer[channel])
  121.         {
  122.             int newpos;
  123.             int buflen;
  124.  
  125.  
  126.             newpos = SAMPLES_THIS_FRAME(channel);
  127.  
  128.             buflen = newpos - stream_buffer_pos[channel];
  129.  
  130.             if (stream_joined_channels[channel] > 1)
  131.             {
  132.                 INT16 *buf[MIXER_MAX_CHANNELS];
  133.  
  134.  
  135.                 if (buflen > 0)
  136.                 {
  137.                     for (i = 0;i < stream_joined_channels[channel];i++)
  138.                         buf[i] = stream_buffer[channel+i] + stream_buffer_pos[channel+i];
  139.  
  140.                     (*stream_callback_multi[channel])(stream_param[channel],buf,buflen);
  141.                 }
  142.  
  143.                 for (i = 0;i < stream_joined_channels[channel];i++)
  144.                     stream_buffer_pos[channel+i] = 0;
  145.  
  146.                 for (i = 0;i < stream_joined_channels[channel];i++)
  147.                     apply_RC_filter(channel+i,stream_buffer[channel+i],buflen,stream_sample_rate[channel+i]);
  148.             }
  149.             else
  150.             {
  151.                 if (buflen > 0)
  152.                 {
  153.                     INT16 *buf;
  154.  
  155.  
  156.                     buf = stream_buffer[channel] + stream_buffer_pos[channel];
  157.  
  158.                     (*stream_callback[channel])(stream_param[channel],buf,buflen);
  159.                 }
  160.  
  161.                 stream_buffer_pos[channel] = 0;
  162.  
  163.                 apply_RC_filter(channel,stream_buffer[channel],buflen,stream_sample_rate[channel]);
  164.             }
  165.         }
  166.     }
  167.  
  168.     for (channel = 0;channel < MIXER_MAX_CHANNELS;channel += stream_joined_channels[channel])
  169.     {
  170.         if (stream_buffer[channel])
  171.         {
  172.             for (i = 0;i < stream_joined_channels[channel];i++)
  173.                 mixer_play_streamed_sample_16(channel+i,
  174.                         stream_buffer[channel+i],sizeof(INT16)*SAMPLES_THIS_FRAME(channel+i),
  175.                         stream_sample_rate[channel]);
  176.         }
  177.     }
  178. }
  179.  
  180.  
  181. int stream_init(const char *name,int default_mixing_level,
  182.         int sample_rate,
  183.         int param,void (*callback)(int param,INT16 *buffer,int length))
  184. {
  185.     int channel;
  186.  
  187.  
  188.     channel = mixer_allocate_channel(default_mixing_level);
  189.  
  190.     stream_joined_channels[channel] = 1;
  191.  
  192.     mixer_set_name(channel,name);
  193.  
  194.     if ((stream_buffer[channel] = malloc(sizeof(INT16)*BUFFER_LEN)) == 0)
  195.         return -1;
  196.  
  197.     stream_sample_rate[channel] = sample_rate;
  198.     stream_buffer_pos[channel] = 0;
  199.     if (sample_rate)
  200.         stream_sample_length[channel] = 1000000 / sample_rate;
  201.     else
  202.         stream_sample_length[channel] = 0;
  203.     stream_param[channel] = param;
  204.     stream_callback[channel] = callback;
  205.     set_RC_filter(channel,0,0,0,0);
  206.  
  207.     return channel;
  208. }
  209.  
  210.  
  211. int stream_init_multi(int channels,const char **names,const int *default_mixing_levels,
  212.         int sample_rate,
  213.         int param,void (*callback)(int param,INT16 **buffer,int length))
  214. {
  215.     int channel,i;
  216.  
  217.  
  218.     channel = mixer_allocate_channels(channels,default_mixing_levels);
  219.  
  220.     stream_joined_channels[channel] = channels;
  221.  
  222.     for (i = 0;i < channels;i++)
  223.     {
  224.         mixer_set_name(channel+i,names[i]);
  225.  
  226.         if ((stream_buffer[channel+i] = malloc(sizeof(INT16)*BUFFER_LEN)) == 0)
  227.             return -1;
  228.  
  229.         stream_sample_rate[channel+i] = sample_rate;
  230.         stream_buffer_pos[channel+i] = 0;
  231.         if (sample_rate)
  232.             stream_sample_length[channel+i] = 1000000 / sample_rate;
  233.         else
  234.             stream_sample_length[channel+i] = 0;
  235.     }
  236.  
  237.     stream_param[channel] = param;
  238.     stream_callback_multi[channel] = callback;
  239.     set_RC_filter(channel,0,0,0,0);
  240.  
  241.     return channel;
  242. }
  243.  
  244.  
  245. /* min_interval is in usec */
  246. void stream_update(int channel,int min_interval)
  247. {
  248.     int newpos;
  249.     int buflen;
  250.  
  251.  
  252.     if (Machine->sample_rate == 0 || stream_buffer[channel] == 0)
  253.         return;
  254.  
  255.     /* get current position based on the timer */
  256.     newpos = sound_scalebufferpos(SAMPLES_THIS_FRAME(channel));
  257.  
  258.     buflen = newpos - stream_buffer_pos[channel];
  259.  
  260.     if (buflen * stream_sample_length[channel] > min_interval)
  261.     {
  262.         if (stream_joined_channels[channel] > 1)
  263.         {
  264.             INT16 *buf[MIXER_MAX_CHANNELS];
  265.             int i;
  266.  
  267.  
  268.             for (i = 0;i < stream_joined_channels[channel];i++)
  269.                 buf[i] = stream_buffer[channel+i] + stream_buffer_pos[channel+i];
  270.  
  271.             profiler_mark(PROFILER_SOUND);
  272.             (*stream_callback_multi[channel])(stream_param[channel],buf,buflen);
  273.             profiler_mark(PROFILER_END);
  274.  
  275.             for (i = 0;i < stream_joined_channels[channel];i++)
  276.                 stream_buffer_pos[channel+i] += buflen;
  277.         }
  278.         else
  279.         {
  280.             INT16 *buf;
  281.  
  282.  
  283.             buf = stream_buffer[channel] + stream_buffer_pos[channel];
  284.  
  285.             profiler_mark(PROFILER_SOUND);
  286.             (*stream_callback[channel])(stream_param[channel],buf,buflen);
  287.             profiler_mark(PROFILER_END);
  288.  
  289.             stream_buffer_pos[channel] += buflen;
  290.         }
  291.     }
  292. }
  293.